from django.core import serializers
from django.forms import model_to_dict
from django.http import JsonResponse,HttpResponse
from django.shortcuts import render
from math import exp,log10
from django.views.decorators.http import require_http_methods
from rest_framework.utils import json
from .models import collection,buy,transaction
import requests
import random as rand
import pandas as pd
import numpy as np
import random
import baostock as bs
def get_history_data(code):
    '''
    @ans_list:
    [0]:trading date
    [1]:PE
    [2]:PB
    [3]:PS
    [4]:turnover
    [5]:circulated market value
    [6]:change ratio
    [7]:amount
    [8]:liquidility
    '''
    # import pandas as pd
    result_csv=pd.read_csv(r'F:\谷歌下载\vue-secondMenu-test-master\jht201850035\app01\001.csv',encoding='utf-8')
    data=pd.DataFrame(result_csv,columns=['TradingDate','Symbol','PE','PB','PS','Turnover','CirculatedMarketValue','ChangeRatio','Amount','Liquidility'])
    #data.info()
    ans_list=[]
    for index,row in data.iterrows():
        if row['Symbol']==int(code):
            ans_list.append([row['TradingDate'],row['PE'],row['PB'],\
                row['PS'],row['Turnover'],row['CirculatedMarketValue'],\
                    row['ChangeRatio'],row['Amount'],row['Liquidility']])
            # print (type(ans_list[0][1]))
    return ans_list

def check_collection(request):
    if(request.method=='GET'):
        contentset=[]
        content=collection.objects.all()
        for i in content:
            temp=model_to_dict(i)
            contentset.append(temp)
        return JsonResponse(contentset,safe=False)


def add_collection(request):
    res={}
    res['code']=0
    res['message']='no!'
    if(request.method=='POST'):
        if(request.POST):
            data=json.loads(request.body)
            check=collection.objects.filter(stock_id=data['stock_id'])
            if(check):
                return JsonResponse(res)
            else:
                res['code']=1
                res['message']='yes'
                collection.objects.create(stock_id=data['stock_id'])
                return JsonResponse(res)
    return JsonResponse(res)


def buy_stock(request):
    res={}
    res['code']=0
    res['message']='no!'
    if(request.method=='POST'):
        if(request.POST):
            res['code']=1
            res['message']='ok!'
            data=json.loads(request.body)#使用json.loads对数据类型进行转换
            check=buy.objects.filter(stock_id=data['stock_id'])
            if(check):
                check=model_to_dict(check.first())
                buy.objects.filter(stock_id=data['stock_id']).update(volume=(check['volume']+int(data['volume'])))
                transaction.objects.create(trans_type='buy',stock_id=data['stock_id'],stock_name=data['stock_name'],trans_price=rand.uniform(20,50),trans_volume=data['volume'])
            else:
                buy.objects.create(stock_id=data['stock_id'],stock_name=data['stock_name'],volume=int(data['volume']))
                transaction.objects.create(trans_type='buy',stock_id=data['stock_id'],stock_name=data['stock_name'],trans_price=rand.uniform(20,50),trans_volume=data['volume'])
            return JsonResponse(res)
        else:
            return JsonResponse(res)

    return JsonResponse(res)



def sell_stock(request):
    res={}
    res['code']=0
    res['message']='fail!'
    if(request.method=='POST'):
        if(request.POST):
            data=json.loads(request.body)#前端传来的数据
            check=buy.objects.filter(stock_id=data['stock_id'])#数据库中的数据
            if(check):
                check=model_to_dict(check.first())
                if(check['volume']<int(data['volume'])):
                    return JsonResponse(res)
                else:
                    res['code']=1
                    res['message']='success!'
                    if((check['volume']-int(data['volume']))>0):
                        buy.objects.filter(stock_id=data['stock_id']).update(volume=(check['volume']-int(data['volume'])))
                        transaction.objects.create(trans_type='sell',stock_id=data['stock_id'],stock_name=data['stock_name'],trans_price=rand.uniform(20,50),trans_volume=data['volume'])
                    else:
                        buy.objects.filter(stock_id=data['stock_id']).delete()
                        transaction.objects.create(trans_type='sell',stock_id=data['stock_id'],stock_name=data['stock_name'],trans_price=rand.uniform(20,50),trans_volume=data['volume'])
                    return JsonResponse(res)
            else:
                return JsonResponse(res)
    return JsonResponse(res)


def check_buy(request):
    if(request.method=='GET'):
        idindex=[]
        contentset=[]
        content=buy.objects.all()
        for i in range(1,len(content)+1):
            idindex.append(i)
        for i in content:
            temp=model_to_dict(i)
            contentset.append(temp)
        return JsonResponse(contentset,safe=False)

def check_history(request):
     if(request.method=='GET'):
        idindex=[]
        contentset=[]
        content=transaction.objects.all()
        for i in range(1,len(content)+1):
            idindex.append(i)
        for i in content:
            temp=model_to_dict(i)
            contentset.append(temp)
        print(contentset)
        return JsonResponse(contentset,safe=False)


#获取自变量的函数
def get_delta(x,testvol):
    return np.array(x[1:testvol])-np.array(x[0:testvol-1])

#对自变量进行标准化的函数
def datastd(x):
    return np.array((x-np.mean(x))/np.std(x))

#在矩阵中添加常数列
def add_one_column(x):
    return np.hstack([np.ones((x.shape[0],1)),x])

#reshape的工具
def resh(x):
    return x.reshape(-1,1)

#theta and x should be numpy vector
def logistic_sigmoid_function(theta,x):
    return 1/(1+exp(-x@theta))

def logistic_cal_partial(index,matrix,theta,y):#算出theta_j的偏导数
    sum=0
    for i in range(0,matrix.shape[0]):#行
        sum=sum+(logistic_sigmoid_function(theta,matrix[i,:])-y[i])*matrix[i,index]
    return sum/matrix.shape[0]

def logistic_cost_function(matrix,theta,y):
    sum=0
    for i in range(0,matrix.shape[0]):
        sum=sum+(y[i]*log10(logistic_sigmoid_function(theta,matrix[i,:])+0.0001)+(1-y[i])*log10(1-logistic_sigmoid_function(theta,matrix[i,:])+0.0001))
    return -(sum/matrix.shape[0])

#对于实数的sigmoid_function
def status_sig(x):
    return 1/(1+np.exp(-x))

#sig函数的导数
def status_d_sig(x):
    return np.exp(-x)/((1+np.exp(-x))**2)


#对于实数的sigmoid_function
def neural_sig1(x):
    return (2/(1+np.exp(-x)))-1


#sig函数的导数
def neural_d_sig1(x):
    return 2*(np.exp(-x)/((1+np.exp(-x))**2))


#对于实数的sig2 func
def neural_sig2(x):
    return (np.exp(x)-np.exp(-x))/(np.exp(x)+np.exp(-x))


#sig2 func的导数
def neural_d_sig2(x):
    return 4/((np.exp(x)+np.exp(-x))**2)


#对于实数的sig3 func
def neural_sig3(x):
    return 2*np.pi*np.arctan(x)

#sig3 func的导数
def neural_d_sig3(x):
    return 2/(np.pi*(1+(np.array(x)**2)))

#对于实数的sig4 func
def neural_sig4(x):
    return (np.exp(0.65*x)-np.exp(-0.65*x))/(np.exp(0.65*x)+np.exp(-0.65*x))

#sig4 func的导数
def neural_d_sig4(x):
    return 0.65*4/((np.exp(0.65*x)+np.exp(-0.65*x))**2)

def get_temp_data(code):
    '''
    res[0]:股票代码
    res[1]:静态市盈率
    res[2]:市净率
    -----
    res[3]:换手率
    res[4]:流通市值
    res[5]:成交金额
    --------
    '''
    url01='http://qt.gtimg.cn/q=sz'+code
    url02='http://qt.gtimg.cn/q=sh'+code
    res=[]
    data01=requests.get(url01).text.split('~')
    data02=requests.get(url02).text.split('~')
    bool1='v_pv_none_match="1"' in data01[0] 
    bool2='v_pv_none_match="1"' in data02[0]
    if bool1 and bool2:
        # res['error_code']='0'
        pass
    else:
        if bool1==False:
            data=data01
        elif bool2 == False:
            data=data02
        res.append(code)
        res.append(data[53])
        res.append(data[46])
        res.append(3)
        res.append(data[38])
        res.append(data[44])
        res.append(data[37])
        res.append(0.00001)
    return res
        # lg=bs.login()
        # profit_list = []
        # rs_profit = bs.query_profit_data(code="sh.600000", year=2017, quarter=2)
        # while (rs_profit.error_code == '0') & rs_profit.next():
        #     profit_list.append(rs_profit.get_row_data())
        # result.profit = pd.DataFrame(profit_list,columns=rs_profit.fields)
        # res.append(/result.profit)
        
def predict_stock(request):
    res={}
    res['code']=0
    res['message']='fail!'

    if request.method=='POST':
        if request.POST:
            res['code']=1
            res['message']='success'
            print('start!')
            #---------------------------学习率设定-----------------------------
            logistic_alpha=0.08 #logistic涨跌判别的学习率
            status_alpha=0.18#status判别的学习率
            neural_alpha=0.255#neural预测的学习率
            #----------------------------------------------------------------

            #------------------------参数矩阵的随机初始化------------------------
            status_theta_1=np.random.rand(7,8)-0.5
            status_theta_2=np.random.rand(6,7)-0.5
            logistic_theta=[]
            for i in range(0,8):
                logistic_theta.append(random.uniform(0,5))
            logistic_theta=np.array(logistic_theta).reshape(-1,1)
            neural_theta_1=np.random.rand(22,22)
            neural_theta_2=np.random.rand(15,22)
            neural_theta_3=np.random.rand(11,15)
            neural_theta_4=np.random.rand(3,11)
            #-----------------------------------------------------------------

            reception=json.loads(request.body)
            stock_id=reception['stock_id']#拆出股票代码


            #------------------the six status---------------------------------
            status_1=np.array([1,0,0,0,0,0]).reshape(-1,1)
            status_2=np.array([0,1,0,0,0,0]).reshape(-1,1)
            status_3=np.array([0,0,1,0,0,0]).reshape(-1,1)
            status_4=np.array([0,0,0,1,0,0]).reshape(-1,1)
            status_5=np.array([0,0,0,0,1,0]).reshape(-1,1)
            status_6=np.array([0,0,0,0,0,1]).reshape(-1,1)
            #-----------------------------------------------------------------



            #-----------------------原始数据集----------------------------------
            #print(get_history_data(stock_id))
            data=np.mat(get_history_data(stock_id))#数据矩阵
            pe=data[:,1]
            pe=pe.astype('float64')
            pe=resh(datastd(get_delta(pe,len(pe))))
            pb=data[:,2]
            pb=pb.astype('float64')
            pb=resh(datastd(get_delta(pb,len(pb))))
            ps=data[:,3]
            ps=ps.astype('float64')
            ps=resh(datastd(get_delta(ps,len(ps))))
            turnover=data[:,4]
            turnover=turnover.astype('float64')
            turnover=resh(datastd(get_delta(turnover,len(turnover))))
            cmv=data[:,5]
            cmv=cmv.astype('float64')
            cmv=resh(datastd(get_delta(cmv,len(cmv))))
            amount=data[:,7]
            amount=amount.astype('float64')
            amount=resh(datastd(get_delta(amount,len(amount))))
            liquid=data[:,8]
            liquid=liquid.astype('float64')
            liquid=resh(datastd(get_delta(liquid,len(liquid))))
            changeratio=np.mat(data[:,6])
            changeratio=changeratio.astype('float64')
            cr=np.array(changeratio[1:len(changeratio)])
            mat=np.mat(np.hstack((pe,pb,ps,turnover,cmv,amount,liquid)))
           


            mat_1=np.mat(mat[0:mat.shape[0]-2,:])
            #mat_1[:,4]=mat_1[:,4]/100000000000
            #mat_1[:,5]=mat_1[:,5]/1000000000
            mat_2=np.mat(mat[1:mat.shape[0]-1,:])
            #mat_2[:,4]=mat_2[:,4]/100000000000
            #mat_2[:,5]=mat_2[:,5]/1000000000
            mat_3=np.mat(mat[2:mat.shape[0],:])
            #mat_3[:,4]=mat_3[:,4]/100000000000
            #mat_3[:,5]=mat_3[:,5]/1000000000
            neural_x_mat=np.mat(np.hstack((mat_1,mat_2,mat_3)))
            neural_x_mat=np.mat(add_one_column(neural_x_mat))
            mat=add_one_column(mat)#mat为基本数据
            #x_mat为neural network预测中所需要的基础数据矩阵
            #---------------------------------------------------

            #--------------neural network的因变量向量--------------------
            cr_1=np.mat(changeratio[1:len(changeratio)-2])
            cr_2=np.mat(changeratio[2:len(changeratio)-1])
            cr_3=np.mat(changeratio[3:len(changeratio)])
            y_mat=np.mat(np.hstack((cr_1,cr_2,cr_3)))
            print(y_mat)
            #----------------------------------------------------------
            #爬虫获得了当前的数据
            getfrom=get_temp_data(stock_id)
            getfrom=np.array(getfrom).reshape(-1,1)
            
            print("11111111111111111111111111111")
            #----------------------logistic regression------------------
            logistic_result=[]#将涨跌幅变换成0，1的布尔值
            for i in cr:
                if(i>=0):
                    logistic_result.append(1)
                else:
                    logistic_result.append(0)
            for i in range(0,1000):
                partial=[]
                for j in range(0,8):
                    partial.append(logistic_cal_partial(j,mat,logistic_theta,logistic_result))
                partial=np.array(partial).reshape(-1,1)
                logistic_theta=logistic_theta-logistic_alpha*partial

            
            # del logistic_theta[7]
            logistic_theta=np.array(logistic_theta)

            if(logistic_theta@getfrom>0.8):
                res['up_or_down']='up'
            else:
                res['up_or_down']='down'
            #----------------------------------------------------------
            print("222222222222222222222222222222222")

            #------------neural network status-------------------------
            #正式开始神经网络的参数调整，以theta_1和theta_2为基础
            for time in range(0,1200):
                #参数的变化量矩阵
                d_1=np.zeros((7,8))
                d_2=np.zeros((6,7))
                for i in range(0,len(cr)):
                #res是真实的状态向量
                    if(cr[i]>0.045):
                        res=status_1
                    if(cr[i]>0.015 and cr[i]<=0.045):
                        res=status_2
                    if(cr[i]>0 and cr[i]<=0.015):
                        res=status_3
                    if(cr[i]>-0.015 and cr[i]<=0):
                        res=status_4
                    if(cr[i]>-0.045 and cr[i]<=-0.015):
                        res=status_5
                    if(cr[i]<=-0.045):
                        res=status_6
                    x_1=np.array(mat[i,:])#input vector 1*7
                    y_1=status_theta_1@(x_1.T)#7*1
                    x_2=np.array(status_sig(y_1)).reshape(-1,1)#7*1
                    y_2=status_theta_2@(x_2)#6*1
                    predict=np.array(status_sig(y_2)).reshape(-1,1)#6*1
                    err_3=predict-res#预测处的误差 #6*1
                    err_2=np.multiply(((status_theta_2.T)@err_3),np.array(status_d_sig(y_1)).reshape(-1,1))#隐藏层的误差 #7*1
                    d_2=d_2+err_3@(x_2.T)
                    d_1=d_1+err_2@(x_1)
                d_2=d_2/len(cr)
                d_1=d_1/len(cr)
                status_theta_1=status_theta_1-status_alpha*d_1
                status_theta_2=status_theta_2-status_alpha*d_2

            print(status_theta_1)
            status_theta_1=np.mat(status_theta_1)
            status_theta_2=np.mat(status_theta_2)
            y_1=status_theta_1@getfrom
            y_1=np.array(status_sig(y_1)).reshape(-1,1)
            y_2=status_theta_2@(y_1)
            y_2=status_sig(y_2).reshape(-1,1)
            if(cr[i]>0.045):
                res['status']='up more than 4.5%'
            if(cr[i]>0.015 and cr[i]<=0.045):
                res['status']='up between 1.5% and 4.5%'
            if(cr[i]>0 and cr[i]<=0.015):
                res['status']='up between 0 and 1.5%'
            if(cr[i]>-0.015 and cr[i]<=0):
                res['status']='down between 0 and 1.5%'
            if(cr[i]>-0.045 and cr[i]<=-0.015):
                res['status']='down between 1.5% and 4.5%'
            if(cr[i]<=-0.045):
                res['status']='down more than 4.5%'


            #----------------------------------------------------------
            print("333333333333333333333333")
            #------------------neural---------------------------------
            for time in range(0,500):
                d_1=np.zeros((22,22))
                d_2=np.zeros((15,22))
                d_3=np.zeros((11,15))
                d_4=np.zeros((3,11))
                for i in range(0,y_mat.shape[0]):
                    x_1=np.array(neural_x_mat[i,:])#1*22
                    y_1=neural_theta_1@(x_1.T) #44*1
                    x_2=np.array(neural_sig4(y_1)).reshape(-1,1) #44*1 
                    y_2=neural_theta_2@x_2 #44*1
                    x_3=np.array(neural_sig3(y_2)).reshape(-1,1) #44*1 
                    y_3=neural_theta_3@x_3 #44*1
                    x_4=np.array(neural_sig2(y_3)).reshape(-1,1) #44*1
                    y_4=neural_theta_4@x_4#3*1
                    predict=np.array(neural_sig1(y_4)).reshape(-1,1) #3*1
                    err_5=predict-np.array(y_mat[i,:]).reshape(-1,1) #3*1
                    err_4=np.multiply(((neural_theta_4.T)@err_5),np.array(neural_d_sig2(y_3)).reshape(-1,1))#44*1
                    err_3=np.multiply(((neural_theta_3.T)@err_4),np.array(neural_d_sig3(y_2)).reshape(-1,1))
                    err_2=np.multiply(((neural_theta_2.T)@err_3),np.array(neural_d_sig4(y_1)).reshape(-1,1))
                    d_4=d_4+err_5@(x_4.T)
                    d_3=d_3+err_4@(x_3.T)
                    d_2=d_2+err_3@(x_2.T)
                    d_1=d_1+err_2@(x_1)
                d_4=d_4/y_mat.shape[0]
                d_3=d_3/y_mat.shape[0]
                d_2=d_2/y_mat.shape[0]
                d_1=d_1/y_mat.shape[0]
                neural_theta_4=neural_theta_4-neural_alpha*d_4
                neural_theta_3=neural_theta_3-neural_alpha*d_3
                neural_theta_2=neural_theta_2-neural_alpha*d_2
                neural_theta_1=neural_theta_1-neural_alpha*d_1
            print(neural_theta_1)
            print(neural_theta_2)
            print(neural_theta_3)
            print(neural_theta_4)
            y_1=neural_theta_1@getfrom #44*1
            x_2=np.array(neural_sig4(y_1)).reshape(-1,1) #44*1 
            y_2=neural_theta_2@x_2 #44*1
            x_3=np.array(neural_sig3(y_2)).reshape(-1,1) #44*1 
            y_3=neural_theta_3@x_3 #44*1
            x_4=np.array(neural_sig2(y_3)).reshape(-1,1) #44*1
            y_4=neural_theta_4@x_4#3*1
            predict=np.array(neural_sig1(y_4)).reshape(-1,1) #3*1
            res['first_day']=predict[0]
            res['second_day']=predict[1]
            res['third_day']=predict[2]
            #--------------------------------------------------------
    return JsonResponse(res,safe=False)
    

def get_stockinfo(request):
    if request.method == 'POST':
        print(request.POST)
        if request.POST:
            stock_data= json.loads(request.body.decode('utf-8'))
            print (stock_data)
            code=stock_data['stockcode']    
            url01='http://qt.gtimg.cn/q=sz'+code
            url02='http://qt.gtimg.cn/q=sh'+code
            res={}
            data01=requests.get(url01).text.split('~')
            data02=requests.get(url02).text.split('~')
            bool1='v_pv_none_match="1"' in data01[0] 
            bool2='v_pv_none_match="1"' in data02[0]
            if bool1 and bool2:
                res['error_code']='0'
            else:
                if bool1==False:
                    data=data01
                    res['type']='sz'+data[2]
                elif bool2 == False:
                    data=data02
                    res['type']='sh'+data[2]
                res['error_code']='1'
                res['stockid']=data[2]
                res['stockname']=data[1]
                res['stockprice']=data[3]
                res['price_change']=data[31]
                res['percentage']=data[32]+'%'
                res['liangbi']=data[49]
                res['high']=data[33]
                res['low']=data[34]
                res['highest']=data[47]
                res['lowest']=data[48]
                res['today']=data[5]
                res['yesterday']=data[4]
                res['volume']=data[36]
                res['volume_price']=data[37]
                res['huanshou']=data[38]+'%'
                res['shiyinglvdong']=data[52]
                res['shiyinglvjing']=data[53]
                res['shijinglv']=data[46]
                res['shiyinglvttm']=data[39]
                # res['meigushouyi']=
                # res['guxi']=
                # res['zongguben']=
                res['zongshizhi']=data[45]+'亿'
                # res['meigujinzichan']=
                # res['guxilv']=
                # res['liutonggu']=
                res['liutongzhi']=data[44]
                res['zhenfu']=data[43]
            # print (res)
            return JsonResponse(res)
    




